home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * NNTP Server/Client Subroutines - See RFC977
- * Jeffrey R. Comstock. - NR0D - Bloomington, Minnesota USA
- * Copyright 1990 Jeffrey R. Comstock, All Rights Reserved.
- * Permission granted for non-commercial copying and use, provided
- * this notice is retained.
- *
- * DB3FL 9107xx: heavily rewritten and bug fixing in file-handling
- * DB3FL 920121: splitted into several files
- * DG1ZX 9210xx: bug fixing and optimize
- * DG1ZX 9303xx: included POST and XDHR command
- * DG1ZX 930728: included nntp restrictions and history lifetime
- * DG1ZX 941024: fixed bug in xfer_article2() when fullauto = 0 and last
- * newsgroup specified in the article is not in active file
- */
-
- #include <stdio.h>
- #include <time.h>
- #include <dos.h>
- #include <io.h>
- #include <dir.h>
- #include <ctype.h>
- #include <sys/stat.h>
-
- #include "global.h"
- #include "nntp.h"
- #include "files.h"
- #include "socket.h"
-
-
- int Filecheck = 0;
- int16 Nntpquiet = 0;
-
- char *Host = NULLCHAR;
-
- /* main directory-creating routine
- * handles special chars in pathname - especially for MSDOS
- * returncode: -1 error; 0 success
- */
- static int near
- make_dir(char *path,int s)
- {
- char *cp;
-
- if(path == NULLCHAR)
- return -1;
-
- while((cp = strchr(path,'\\')) != NULLCHAR)
- *cp = '/';
-
- if (access(path,0)) {
- if (mkdir(path)) {
- tprintf("Can't create %s: %s\n",path,sys_errlist[errno]);
- if(s)
- usprintf(s,fatal,path);
- return -1;
- }
- }
- return 0;
- }
-
- /* creating path to a new newsgroup
- * handling of "." and "\" in pathnames and length of filename
- * especially MSDOS
- * returncode: -1 error; 0 success */
- int make_path(char *group,char w)
- {
- FILE *f;
- char cp[LineLen], cp1[LineLen], *cp2;
- int got_it = 0, i, n = 0, len = 0;
-
- if (group == NULLCHAR
- || (f = open_file(Pointer,APPEND_TEXT,0,1)) == NULLFILE)
- return -1;
-
- strcpy(cp1,group);
-
- for(;;) {
- if((cp2 = strchr(cp1,'.')) != NULLCHAR)
- *cp2 = '\0';
- else
- got_it = 1;
-
- sprintf(cp,"%s/%s",News,cp1);
-
- /* make subdir step by step */
- if(make_dir(cp,0)) {
- fclose(f);
- return -1;
- }
-
- if(got_it) {
- if(w) {
- /* now add new newgroup and path to pointer file */
- for (i = 0;cp[i] != NULL;i++) {
- if (cp[i] == '/')
- len = 0;
- /* length limit handling of DOS filename */
- if (len < MAXFILE)
- cp1[n++] = cp[i];
- len ++;
- }
- cp1[n] = '\0';
- fprintf(f,"%s %s\n",group,cp1);
- }
- fclose(f);
- return 0;
- }
- *cp2 = '/';
- }
- }
-
-
- static int near
- update_list(struct nntpsv *a)
- {
- FILE *f, *t;
- char *p, *p1, l2[LineLen];
-
- if((f = open_file(Active,READ_TEXT,a->s,0)) == NULLFILE)
- return -1;
-
- if ((t = temp_file(0,1)) == NULLFILE) {
- fclose(f);
- return -1;
- }
- p1 = a->ap->group;
- a->ap->number = 0; /* set highest article number to 0 */
- for (;;) {
- if (fgets(a->buf,LineLen,f) == NULL)
- break;
- a->ap->tmpu = strcspn(a->buf," "); /* Length of newsgroup */
- strncpy(l2,a->buf,a->ap->tmpu); /* copy newsgroup */
- l2[a->ap->tmpu] = '\0';
- if (strcmp(p1,l2) == 0) { /* look for entry */
- p = strchr(a->buf,' ') + 1;
- a->ap->number = (unsigned)atoi(p); /* get number of messages */
- (a->ap->number)++; /* increment number */
- p = strchr(p,' ');
- fprintf(t,"%s %5.5u%s",p1,a->ap->number,p); /* write back updated newsgroup line */
- } else
- fputs(a->buf,t); /* write back existing newsgroup line */
- }
- fclose(f);
- rewind(t);
- if ((f = open_file(Active,WRITE_TEXT,a->s,0)) == NULLFILE) {
- fclose(t);
- return -1;
- }
- for(;;) { /* copy temp. file to active file */
- if (fgets(a->buf,LineLen,t) == NULL)
- break;
- fputs(a->buf,f);
- }
- fclose(t);
- /* highest article in active file = 0 and update allowed ? */
- if ((a->ap->number == 0) && fullauto) {
- /* create new subdirectories and add new group to active file */
- make_path(a->ap->group,1);
- a->ap->number = 1;
- fprintf(f,"%s 00001 00001 y\n",a->ap->group);
- }
- fclose(f);
- return (a->ap->number);
- }
-
- /* main file-checking routine
- * returncode: -1 if error; 0 success */
- static int near
- check_file(char *path)
- {
- if(path == NULLCHAR)
- return -1;
- if(access(path,0))
- return close(creat(path,S_IWRITE));
- return 0;
- }
-
- /* checkes if path to given article exists
- * returncode: -1 error; 1 success; 0 no path */
- int
- get_path2(struct article *art)
- {
- FILE *f;
- char line[LineLen], *p;
-
- if(art->group == NULLCHAR
- || (f = open_file(Pointer,READ_TEXT,0,1)) == NULLFILE)
- return -1;
-
- p = art->group;
- art->path = NULLCHAR;
-
- for (;;) {
- if (fgets(line,LineLen,f) == NULL)
- break;
- if (strcspn(line," ") != strlen(p))
- continue;
- if (strnicmp(p,line,strlen(p)) == 0) {
- p = (strchr(line,' ')) + 1;
- if(art->path != NULLCHAR)
- xfree(art->path);
- art->path = strxdup(p);
- rip2(art->path);
- fclose(f);
- return 1;
- }
- }
- fclose(f);
- return 0;
- }
-
- /* returncode: -1 error; 0 success */
- static int near
- dup_f(FILE *in,FILE *out,struct nntpsv *mp)
- /* Path: bug in col 1 of article body bug fixed by G4JEC 901019....*/
- /* Path-field no more expected in line 1 (DG1ZX) */
- {
- char *p;
- int blank_line_flag = 1;
-
- for(;;) {
- if (fgets(mp->buf,LineLen,in) == NULL)
- return 0;
-
- if (blank_line_flag)
- if (strnicmp(mp->buf,pth,5) == 0) {
- p = strchr(mp->buf,' \t') + 1;
- fprintf(out,"%s%s!%s",pth,Host,p);
- blank_line_flag = 0;
- continue;
- }
- /* oh oh - nntpserv is modifying articles....*/
- if (strlen(mp->buf) == 1 && mp->buf[0] == '.')
- continue;
- fputs(mp->buf,out);
- }
- }
- /*
- copy article to \spool\news\junk and update history and fwd.seq file
- returncode: < 1 if error; 1 success
- */
- static int near
- dofwd(struct nntpsv *mp,FILE *f,FILE *history,char *part1)
- {
- FILE *fwd;
-
- if(mp == NULLNNTPSV)
- return -1;
-
- sprintf(mp->buf,"%s/fwd.seq",News);
- if ((fwd = open_file(mp->buf,"r+",mp->s,0)) == NULLFILE)
- return -1;
-
- fgets(mp->buf,LineLen,fwd);
- mp->hold_i = atoi(mp->buf) + 1;
- fprintf(history,"%s JUNK/%u\n",part1,mp->hold_i);
- rewind(fwd);
- fprintf(fwd,"%u",mp->hold_i);
- fclose(fwd);
-
- sprintf(mp->buf,"%s/%u",Forward,mp->hold_i);
- if ((fwd = open_file(mp->buf,WRITE_TEXT,mp->s,0)) == NULLFILE)
- return -2;
-
- rewind(f);
- dup_f(f,fwd,mp);
- fclose(fwd);
- return 1;
- }
-
- /* checks the file-system used for NNTP
- * returncode: -1 if error; 0 success - and "Filecheck" is set to 1 */
- int
- check_system(void)
- {
- FILE *f;
- char line[LineLen], *cp, *cp1;
- int error = 0;
-
- if (Host == NULLCHAR) {
- cp = strxdup(Hostname);
- if((cp1 = strchr(cp,'.')) != NULLCHAR)
- *cp1 = '\0';
- Host = strxdup(cp);
- xfree(cp);
- }
-
- if(Filecheck)
- return 0;
-
- error = make_dir(Forward,0);
- error |= check_file(Pointer);
- error |= check_file(History);
- error |= check_file(Active);
- error |= check_file(Poll);
-
- if(error)
- goto quit;
-
- sprintf(line,"%s/fwd.seq",News);
- if (access(line,0)) {
- if((f = open_file(line,"w+",0,1)) == NULLFILE) {
- goto quit;
- }
- fputs("1\n",f);
- fclose(f);
- }
- sprintf(line,"%s/sequence.seq",Mailqdir);
- if (access(line,0)) {
- if((f = open_file(line,"w+",0,1)) == NULLFILE) {
- goto quit;
- }
- fputs("1\n",f);
- fclose(f);
- }
- Filecheck = 1;
- return 0;
-
- quit:
- Filecheck = 0;
- tputs("Error in NNTP file system\n");
- return -1;
- }
-
- void
- rip2(char *s)
- {
- char *cp;
-
- if((cp = strpbrk(s,"\r\n")) != NULLCHAR)
- *cp = '\0';
- }
-
- /* file-receiving routine
- * returncode: -1 if error or 'recvline' faults; 0 success; 1 if blank line */
- int
- recv_file(FILE *fp,int s)
- {
- char line[LineLen];
- int check = 0;
-
- for (;;) {
- if (recvline(s,line,LineLen) == -1)
- return -1;
- rip2(line);
-
- if(strcmp(line,".") == 0)
- return 0;
-
- if(!check) { /* only enabled on first line! */
- check = 1;
- if (*line == '\0') /* check for blank line */
- return 1;
- }
- fprintf(fp,"%s\n",line);
- }
- }
-
- /* checks incoming article-id against existing articles
- * returncode: -1 if error; 1 if article exists; 0 no article found */
- int
- check_article(char *id)
- {
- char *p, line[LineLen];
- FILE *f;
-
- if(id == NULLCHAR || (p = strchr(id,'<')) == NULLCHAR
- || (f = open_file(History,READ_TEXT,0,1)) == NULLFILE)
- return -1;
-
- for(;;) {
- if (fgets(line,LineLen,f) == NULL) {
- fclose(f);
- return 0;
- }
- if (strstr(line,p) != NULL) {
- fclose(f);
- return 1;
- }
- }
- }
-
- #ifdef NNTPLIFETIME
- /***************************************************************/
- /* */
- /* Parse a line for date and time in Arpanet format */
- /* (Day, day Month year hh:mm:ss Zone) and return unixtime. */
- /* Interpret date/time always as local time, except we found */
- /* GMT or UT(C) in header field */
- /* */
- /* return = 0 ==> error */
- /* <> 0 ==> unixtime (GMT) */
- /* */
- /***************************************************************/
-
- time_t
- articletime(char *line)
- {
- char buf[13], *cp = line;
- int i, day, year;
- time_t unixtime;
- struct date *datest;
- struct time *timest;
-
- /* skip initial blanks and optional day-of-week */
- while(!isdigit(*cp))
- ++cp;
-
- /* test minimum length */
- if( (*cp == '\0') || (strlen(cp) < 14) )
- return (time_t)0;
-
- /* get day */
- day = atoi(cp);
-
- /* get month */
- cp = strpbrk(cp," ") + 1;
- for(i=0; i < 12; ++i)
- if(strnicmp(Months[i],cp,3) == 0)
- break;
- if(i == 12)
- return (time_t)0;
-
- /* get year (some newsreader uses year with century) */
- if ( (cp = strpbrk(cp," ")) == NULLCHAR)
- return (time_t)0;
- year = atoi(++cp);
- if (year > 99)
- year %= 100;
- cp = strpbrk(cp," ") + 1;
-
- sprintf(buf,"%02d%02d%02d %02d%02d%02d", year, i + 1, day, atoi(cp),
- atoi(cp + 3), *(cp + 5) == ':' ? atoi(cp + 6) : 0 );
-
- datest = (struct date *)mxallocw(sizeof(struct date));
- timest = (struct time *)mxallocw(sizeof(struct time));
- unixtime = make_nntime(datest,timest,buf);
- xfree(timest);
- xfree(datest);
-
- /* error in make_nntime() ? */
- if(!unixtime)
- return (time_t)0;
-
- /* if timezone is not GMT, interpretation as local time. So add */
- /* timeoffset to get GMT */
- if ( (strstr(cp,"GMT") == NULLCHAR) && (strstr(cp,"UT") == NULLCHAR) )
- unixtime+=timezone;
-
- return unixtime;
- }
- #endif
-
- int
- xfer_article2(FILE *f,struct nntpsv *mp)
- {
- char line[LineLen], *p, *p1, *group = NULLCHAR, *from = NULLCHAR;
- char his[LineLen], l[LineLen];
- #ifdef NNTPLIFETIME
- char *date_time = NULLCHAR;
- #endif
- FILE *fptr, *history;
- struct tm *stm;
- int x;
- #ifdef CONTROL
- int control = 0;
- #endif
-
- if(f == NULLFILE || mp == NULLNNTPSV ||
- (history = open_file(History,APPEND_TEXT,mp->s,0)) == NULLFILE) {
- xfree(mp->id);
- return -1;
- }
- if((mp->ap = (struct article *)mxallocw(sizeof(struct article))) == NULLARTICLE) {
- xfree(mp->id);
- fclose(history);
- return -1;
- }
-
- for (;;) {
- if (fgets(line,LineLen,f) == NULL)
- break;
- rip2(line);
- if(*line == '\0')
- break;
-
- /* FROM: line */
- if (strnicmp(line,frm,6) == 0) {
- p = strchr(line,' ') + 1;
- from = strxdup(p);
- continue;
- }
-
- /* NEWSGROUPS: line */
- if (strnicmp(line,ngrps,12) == 0) {
- p = strchr(line,' ') + 1;
- group = strxdup(p);
- continue;
- }
-
- #ifdef NNTPLIFETIME
- /* DATE: line */
- if (strnicmp(line,ndate,6) == 0) {
- p = strchr(line,' ') + 1;
- date_time = strxdup(p);
- continue;
- }
- #endif
- }
- stm = gmtime(&currtime);
- sprintf(his,"%s %2.2d%2.2d%2.2d %2.2d%2.2d%2.2d",
- mp->id,
- stm->tm_year,stm->tm_mon+1,stm->tm_mday,
- stm->tm_hour,stm->tm_min,stm->tm_sec);
-
- mp->hold_i = 0;
- p = group;
- x = 1;
- #ifdef NNTPLIFETIME
- if ( articletime(date_time) < (currtime+timezone-lifetime*DAYS) )
- x = 0;
- if(date_time != NULLCHAR)
- xfree(date_time);
- #endif
- while (x) {
- if ((p1 = strchr(p,',')) != NULLCHAR) {
- p1 = line; /* get next newsgroup */
- while (*p != ',')
- *(p1++) = *(p++);
- *p1 = '\0';
- p++;
- mp->ap->group = strxdup(line);
- } else {
- mp->ap->group = strxdup(p); /* get last newsgroup */
- x = 0;
- }
-
- update_list(mp);
- if (mp->ap->number > 0) {
- get_path2(mp->ap);
- mp->hold_i = 1;
- sprintf(line,"%s/%u",mp->ap->path,mp->ap->number);
- rewind(f);
- if ((fptr = open_file(line,WRITE_TEXT,mp->s,0)) == NULLFILE) {
- fclose(history);
- xfree(mp->ap->group);
- goto quit;
- }
- dup_f(f,fptr,mp);
- fclose(fptr);
-
- /* build line for history file step by step */
- sprintf(l," %s/%u",mp->ap->group,mp->ap->number);
- strcat(his,l);
-
- #ifdef CONTROL
- if (strcmp(mp->ap->group,"control") == 0)
- control = 1;
- #endif
- if(mp->ap->path != NULLCHAR)
- xfree(mp->ap->path);
- }
- xfree(mp->ap->group);
- }
-
- if (mp->hold_i == 0) {
- if ((x = dofwd(mp,f,history,his)) < 1)
- mp->hold_i = 0;
- /* newsgroup did not exist in active file, so forward it to junk */
- xfree(group);
- group = strxdup("JUNK");
- } else {
- /* update history file */
- fprintf(history,"%s\n",his);
- }
-
- fclose(history);
- if(Nntpquiet < 2)
- tprintf("New mail in newsgroup %s\n from <%s> at %s%s",
- group,from,ctime(&currtime),!Nntpquiet ? "\007" : "");
- if(Nntpquiet == 3)
- log(mp->s,"NNTP new mail <%s>",group);
-
- #ifdef CONTROL
- if (control == 1)
- docontrol(f,mp);
- #endif
- quit:
- xfree(mp->id);
- xfree(mp->ap);
- if(from != NULLCHAR)
- xfree(from);
- if(group != NULLCHAR)
- xfree(group);
- return 0;
- }
-
- /* checks for not valid chars in a line
- * returncode: 0 if valid; 1 if invalid */
- int
- check_blank(char *bp)
- {
- if (strpbrk(bp,"!@#$%^&*()_+=<>,./?~`[]{}\|0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") == NULL)
- return 1;
- return 0;
- }
-
- /* converts timestring to unix-compatible structure
- * returncode: 0 (!!) if error; > 0 success */
- static int32
- make_nntime(struct date *d,struct time *t,char *str)
- {
- char *cp, tmp[3];
-
- if(str == NULLCHAR)
- return 0L;
-
- tmp[2] = '\0';
- cp = str;
-
- strncpy(tmp,cp,2);
-
- d->da_year = atoi(tmp)+1900;
-
- if (d->da_year < 1980)
- d->da_year = 1980;
-
- if (d->da_year > 2099)
- goto quit;
-
- cp+=2;
-
- strncpy(tmp,cp,2);
- d->da_mon = atoi(tmp);
- if (d->da_mon < 1 || d->da_mon > 12)
- goto quit;
-
- cp+=2;
-
- strncpy(tmp,cp,2);
- d->da_day = atoi(tmp);
- if (d->da_day < 1 || d->da_day > 32)
- goto quit;
-
- cp+=3;
-
- strncpy(tmp,cp,2);
- t->ti_hour = atoi(tmp);
- if (/* t->ti_hour < 0 || */ t->ti_hour > 24)
- goto quit;
-
- cp+=2;
-
- strncpy(tmp,cp,2);
- t->ti_min = atoi(tmp);
- if (/* t->ti_min < 0 || */ t->ti_min > 60)
- goto quit;
-
- cp+=2;
-
- strncpy(tmp,cp,2);
- t->ti_sec = atoi(tmp);
- if (/* t->ti_sec < 0 || */ t->ti_sec > 60)
- goto quit;
-
- t->ti_hund = 0;
- return (dostounix(d,t));
- quit :
- return 0L;
- }
-
- /* checks if two spaces exists in given string
- * returncode: -1 if error; 1 success */
- static int near
- check_one(char *str)
- {
- char *cp;
-
- if(str == NULLCHAR || (cp = strchr(str,' ')) == NULLCHAR)
- return -1;
-
- if (strchr(++cp,' ') == NULLCHAR)
- return -1;
-
- return 1;
- }
-
- static int
- restreql(char *w, char *s)
- {
- while (*s && *w) {
- switch (*w) {
- case '*':
- for (w++; *s; s++)
- if (restreql(w, s))
- return 1;
- break;
- default:
- if (*w != *s)
- return 0;
- w++, s++;
- break;
- }
- }
- if (*s)
- return 0;
- while (*w)
- if (*w++ != '*')
- return 0;
-
- return 1;
- }
-
- /* return code 0 = no matches, 1 = match */
- static int near
- ngmatcha(int (*func)(char *,char *),int dflt,struct g_list *ngspec, struct g_list *matchlist)
- {
- int match = dflt;
- char *cp;
- struct g_list *n, *m = matchlist;
-
- for(;;) {
- if ((cp = strchr(m->str,'/')) != NULLCHAR)
- *cp = '\0';
- n = ngspec;
- for (;;) {
- if (n->str[0] == '!') { /* Handle negation */
- if ((*func)(n->str+1, m->str)) {
- match = 0;
- }
- } else {
- if ((*func)(n->str, m->str)) {
- match = 1;
- }
- }
- if (n->next == NULLG)
- break;
- else
- n = n->next;
- }
- if (m->next == NULLG)
- break;
- else
- m = m->next;
- }
- return (match);
- }
-
-
- #if (defined(NNTPRESTRICT) || defined(NNTPLIFETIME))
- /*
- checks if article is newer than date/time specified in string
- and if the groups in the given string matches with the
- newsgroups in historyfile.
- If new news exist, MID from all articles are copied in temporary file
- returncode: -3 if poll time/date is to old
- -2 if request with "*" received
- -1 if error
- 0 if no new news
- 1 if new news available
- */
-
- int
- newnews(char *string,struct nntpsv *mp,FILE *f, char serv_cli)
- {
- char line[LineLen], *cp1, groups[LineLen], *cp = string;
- struct g_list *ng, *hist, *ngp, *histp, *ptr;
- FILE *f1;
- int match, j, i = 1, error = -1;
-
- if (check_one(string) == -1)
- return -1;
-
- /* cut off newsgroups from time/date */
- while (*(cp++) > 32)
- i++;
- if (strlen(cp) < 13)
- return -1;
- strncpy(groups,string,i-1);
- groups[i-1] = '\0';
-
- #ifdef NNTPRESTRICT
- #ifdef undef
- /*
- if desired, don't support request with a single "*" in the poll string.
- */
- if(serv_cli && restrict) { /* subroutine from server ? */
- for (cp1 = groups; *cp1 != NULL; cp1++) {
- if (*cp1 == '*') { /* oops i've got you */
- while (*(++cp1) == '*'); /* skip all "*" */
- if ( (*cp1 == ',') || (*cp1 == NULL)) /* End or "," is following ? */
- return -2; /* send error message */
- }
- if ( (cp1 = strpbrk(cp1,",")) == NULLCHAR) /* set pointer to next group */
- break;
- }
- }
- #endif /* undef */
- /*
- if desired, don't support request with any leading "*"
- e.g. *, *.*, *.*.*. You always have to specify top level group !
- */
- if(serv_cli && restrict) {
- for (cp1 = groups; *cp1 != NULL; cp1++) {
- if (*cp1 == '*') { /* oops i've got you */
- while (*(++cp1) == '*'); /* skip all "*" */
- if (!isalnum(*cp1)) /* ".", "," or NULL is following ? */
- return -2; /* send error message */
- }
- if ((cp1 = strpbrk(cp1,",")) == NULLCHAR) /* set pointer to next group */
- break;
- }
- }
- #endif
-
- /* convert date/time string in unixtime format */
- mp->datest = (struct date *)mxallocw(sizeof(struct date));
- mp->timest = (struct time *)mxallocw(sizeof(struct time));
- if ((mp->unixtime = make_nntime(mp->datest,mp->timest,cp)) < 1)
- goto quit;
-
- #ifdef NNTPLIFETIME
- if (serv_cli && (mp->unixtime < (currtime+timezone-(time_t)lifetime*DAYS)))
- return -3;
- #endif
-
- /* build list of all newsgroups in the given string */
- ng = ngp = (struct g_list *)mxallocw(sizeof(struct g_list));
- cp = groups;
-
- for (;;) {
- if (strchr(cp,',') == NULLCHAR ) {
- ng->str = strxdup(cp);
- ng->next = NULLG;
- break;
- }
- j = strcspn(cp,",");
- ng->str = (char *)mxallocw(j+1);
- strncpy(ng->str,cp,j);
- ng->str[j] = '\0';
- ng->next = (struct g_list *)mxallocw(sizeof(struct g_list));
- ng = ng->next;
- if((cp1 = strchr(cp,',')) != NULLCHAR)
- cp = cp1 + 1;
- else
- break;
- }
-
- /* now compare date/time and newsgroups with all entries in history file */
-
- if ((f1 = open_file(History,READ_TEXT,0,1)) == NULLFILE)
- goto quit1;
-
- error = 0;
- for (;;) {
- if (fgets(line,LineLen,f1) == NULL)
- break;
- rip2(line);
- pwait(NULL);
-
- if ((mp->ftime = make_nntime(mp->datest,mp->timest,strchr(line,' ') + 1)) == 0)
- break; /* something wrong with this line so stop searching */
-
- /* article is older than date/time in given string.
- ==> read next line from history */
- if ((mp->ftime - mp->unixtime) < 0)
- continue;
-
- /* if article is newer then check if newsgroups in given string
- and entry in history matches */
-
- for(i = 3, cp = line; i; --i)
- cp = strchr(cp,' ') + 1;
- histp = (struct g_list *)mxallocw(sizeof(struct g_list));
- hist = histp;
-
- /* build list of all newsgroups from the article */
- for (;;) {
- if (strchr(cp,' ') == NULLCHAR) {
- hist->str = strxdup(cp);
- hist->next = NULLG;
- break;
- }
- j = strcspn(cp," ");
- hist->str = (char *)mxallocw(j+1);
- strncpy(hist->str,cp,j);
- hist->str[j] = '\0';
- hist->next = (struct g_list *)mxallocw(sizeof(struct g_list));
- hist = hist->next;
- if((cp1 = strchr(cp,' ')) != NULLCHAR)
- cp = cp1 + 1;
- else
- break;
- }
-
- /* now check if both list matches */
- match = ngmatcha(restreql,0,ngp,histp);
-
- /* free list of all newsgroups specified in the article */
- ptr = histp;
- for (;;) {
- ptr = histp->next;
- xfree(histp->str);
- xfree(histp);
- histp = ptr;
- if (histp == NULLG)
- break;
- }
- /* if no matches exists then read new line from history */
- if (!match)
- continue;
-
- /* we found a new news, so copy message id to file
- and read next line from history */
-
- error = 1;
- cp = line;
- while ( *cp > 32 )
- fputc(*(cp++),f);
- fputc('\n',f);
-
- }
-
- fclose(f1);
-
- /* free list of all newsgroups specified in the given string */
- quit1:
- ptr = ngp;
- for (;;) {
- ptr = ngp->next;
- xfree(ngp->str);
- xfree(ngp);
- ngp = ptr;
- if (ngp == NULLG)
- break;
- }
- quit:
- rewind(f);
- xfree(mp->datest);
- xfree(mp->timest);
-
- return error;
- }
-
- #else
-
- /*
- checks if article is newer than date/time specified in string
- and if the groups in the given string matches with the
- newsgroups in historyfile.
- If new news exist, MID from all articles are copied in temporary file
- returncode: -1 if error; 0 if no new news; 1 new news available
- */
-
- int
- newnews(char *string,struct nntpsv *mp,FILE *f)
- {
- char *cp1, line[LineLen], groups[LineLen], *cp = string;
- struct g_list *ng, *hist, *ngp, *histp, *ptr;
- FILE *f1;
- int match, j, all = 1, i = 1, error = -1;
-
- if (check_one(string) == -1)
- return -1;
-
- /* cut off newsgroups from time/date */
- while (*(cp++) > 32)
- i++;
- if (strlen(cp) < 13)
- return -1;
- strncpy(groups,string,i-1);
- groups[i-1] = '\0';
-
- if(strcmp(groups,"*") != 0)
- all = 0;
-
- /* convert date/time string in unixtime format */
- mp->datest = (struct date *)mxallocw(sizeof(struct date));
- mp->timest = (struct time *)mxallocw(sizeof(struct time));
- if ((mp->unixtime = make_nntime(mp->datest,mp->timest,cp)) < 1)
- goto quit;
-
- /* build list of all newsgroups in the given string */
- if (!all) {
- ng = ngp = (struct g_list *)mxallocw(sizeof(struct g_list));
- cp = groups;
-
- for (;;) {
- if (strchr(cp,',') == NULLCHAR ) {
- ng->str = strxdup(cp);
- ng->next = NULLG;
- break;
- }
- j = strcspn(cp,",");
- ng->str = (char *)mxallocw(j+1);
- strncpy(ng->str,cp,j);
- ng->str[j] = '\0';
- ng->next = (struct g_list *)mxallocw(sizeof(struct g_list));
- ng = ng->next;
- if((cp1 = strchr(cp,',')) != NULLCHAR)
- cp = cp1 + 1;
- else
- break;
- }
- }
-
- /* now compare date/time and newsgroups with all entries in history file */
-
- if ((f1 = open_file(History,READ_TEXT,0,1)) == NULLFILE)
- goto quit1;
-
- error = 0;
- for (;;) {
- if (fgets(line,LineLen,f1) == NULL)
- break;
- rip2(line);
-
- if ((mp->ftime = make_nntime(mp->datest,mp->timest,strchr(line,' ') + 1)) == 0)
- break; /* something wrong with this line so stop searching */
-
- /* article is older than date/time in given string.
- ==> read next line from history */
- if ((mp->ftime - mp->unixtime) < 0)
- continue;
-
- /* if article is newer then check if newsgroups in given string
- and entry in history matches */
-
- if (!all) {
- for(i = 3, cp = line; i; --i)
- cp = strchr(cp,' ') + 1;
- histp = (struct g_list *)mxallocw(sizeof(struct g_list));
- hist = histp;
-
- /* build list of all newsgroups from the article */
- for (;;) {
- if (strchr(cp,' ') == NULLCHAR) {
- hist->str = strxdup(cp);
- hist->next = NULLG;
- break;
- }
- j = strcspn(cp," ");
- hist->str = (char *)mxallocw(j+1);
- strncpy(hist->str,cp,j);
- hist->str[j] = '\0';
- hist->next = (struct g_list *)mxallocw(sizeof(struct g_list));
- hist = hist->next;
- if((cp1 = strchr(cp,' ')) != NULLCHAR)
- cp = cp1 + 1;
- else
- break;
- }
-
- /* now check if both list matches */
- match = ngmatcha(restreql,0,ngp,histp);
-
- /* free list of all newsgroups specified in the article */
- ptr = histp;
- for (;;) {
- ptr = histp->next;
- xfree(histp->str);
- xfree(histp);
- histp = ptr;
- if (histp == NULLG)
- break;
- }
- /* if no matches exists then read new line from history */
- if (!match)
- continue;
- }
-
- /* we found a new news, so copy message id to file
- and read next line from history */
-
- error = 1;
- cp = line;
- while ( *cp > 32 )
- fputc(*(cp++),f);
- fputc('\n',f);
-
- }
-
- fclose(f1);
-
- /* free list of all newsgroups specified in the given string */
- quit1:
- if (!all) {
- ptr = ngp;
- for (;;) {
- ptr = ngp->next;
- xfree(ngp->str);
- xfree(ngp);
- ngp = ptr;
- if (ngp == NULLG)
- break;
- }
- }
- quit:
- rewind(f);
- xfree(mp->datest);
- xfree(mp->timest);
-
- return error;
- }
- #endif
-
- /*
- * checks for a minimum header:
- * The minimum requirement for an incoming article is that it must have
- * a newsgroups: line, a message-id: line, a date: line, a from: line,
- * a subject: line and a blank line to delimit header from body.
- *
- * returncode: 0 complete; 1 not complete
- *
- */
- int
- garbled(FILE *f)
- {
- char line[LineLen];
- int ok = 0;
-
- rewind(f);
- for(;;) {
- if (fgets(line,LineLen,f) == NULL)
- break;
- if (strnicmp(line,ngrps,12) == 0)
- ok |= 1;
- if (strnicmp(line,msgid,12) == 0)
- ok |= 2;
- if (strnicmp(line,ndate,6) == 0)
- ok |= 4;
- if (strnicmp(line,frm,6) == 0)
- ok |= 8;
- if (strnicmp(line,subj,9) == 0)
- ok |= 16;
- if (check_blank(line))
- break;
- }
- rewind(f);
- return (ok == 31) ? 0 : 1;
- }
-
- /**************************************************************************/
- /* checks id from IHAVE offer against existing articles id received by */
- /* newnews command. When this test passed, checks if one of the hostname */
- /* in pathfield is identical with hostname, we are polling now. (dg1zx) */
- /* */
- /* return-code: 0 = no such article ==> IHAVE ok */
- /* 1 = article already exists ==> don't offer */
- /* */
- /**************************************************************************/
-
- int
- check_ihave (FILE *fp, char *id,struct nntpsv *mp, char *hostn)
- {
- char *p = strchr(id,'<'), *mid, line[LineLen];
- int ret;
-
- /* checks if article is offered in this session from host */
- rewind(fp);
- for (;;) {
- if (fgets(line,LineLen,fp) == NULL)
- break;
- if (strstr(line,p) != NULL)
- return 1;
- }
- if(hostn == NULLCHAR)
- return 0;
-
- /* now we check the pathfield of this article */
- mid = strxdup(id);
- p = strchr(mid,'>')+1;
- *p = '\0'; /* cut off CR LF ! */
- ret = doarticle(mid,mp,0,hostn);
- xfree(mid);
- return ((ret==1) ? 0 : 1);
- }